package com.sea.struct;

import com.google.common.collect.Lists;
import com.sea.struct.annotation.FieldStruct;
import com.sea.struct.annotation.InputTypeStruct;
import com.sea.utils.ByteUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.util.List;

public class InputDataStruct extends DataStruct {

    /**
     * 日志对象
     */
    protected Logger logger = LoggerFactory.getLogger(InputDataStruct.class);

    private byte[] data;

    /**
     * 解析业务数据包
     */
    public void parseData(byte[] data) throws Exception {
        try {
            long htype = this.getClass().getAnnotation(InputTypeStruct.class).value();
            logger.info("\n######################开始解析报文数据Type=" + htype + "######################");
            this.data = data;
            List<Field> fields = Lists.newArrayList(this.getClass().getDeclaredFields());
            int startIndex = 0;
            for (Field field : fields) {
                Class<?> fieldType = field.getType();
                FieldStruct struct = field.getAnnotation(FieldStruct.class);
                int byteLen = struct.value();
                byte[] bytes = getFieldBytes(startIndex, byteLen);
                Object value = null;
                FieldStruct.Type type = struct.type();
                String typeLable = "ASCII";
                if (type.value() == FieldStruct.Type.BIN.value()) {
                    if (fieldType.getName().equals("long")) {
                        typeLable = "BIN-Long";
                        value = ByteUtils.Long(bytes);
                    } else if (fieldType.getName().toLowerCase().equals("java.util.date")) {
                        typeLable = "BIN-Date";
                        value = ByteUtils.Date(bytes);
                    } else if ("java.lang.string".equals(fieldType.getName().toLowerCase())) {
                        typeLable = "BIN-String";
                        // todo 编码修改
                        value = ByteUtils.byteToHex(bytes);
                    }
                } else if (type.value() == FieldStruct.Type.BCD.value()) {
                    typeLable = "BCD";
                    String res = ByteUtils.byteToHex(bytes);
                    value = Integer.parseInt(res, 16);
                } else {
                    value = ByteUtils.String(bytes);
                }
                field.set(this, value);
                startIndex += byteLen;
                logger.info(field.getName() + "(" + typeLable + "[" + byteLen + "])" + ":" + value);
            }
        } catch (Exception e) {
            throw new Exception("解析失败", e);
        }
    }

    private byte[] getFieldBytes(int startIndex, int length) {
        byte[] bytes = new byte[length];
        int index = 0;
        while (length > 0) {
            bytes[index] = this.data[startIndex];
            startIndex += 1;
            index += 1;
            length -= 1;
        }
        return bytes;
    }

}
